#include "headfiles.h"

static bool isDigit(char c) {
    if (c <= '9' && c >= '0') {
        return true;
    }
    
    return false;
}

bool isNumber(string s) {
    int size = s.size();
    int state = 0;
    
    int i = 0;
    // skip all pre space, does not process 'f' as a subfix of a float type
    while (i < size && s[i] == ' ') {
        i++;
    }
    
    while (i < size) {
        switch(state) {
            case 0: // After ' ' and '+' or '-'
                if (s[i] == ' ') {
                    state = 0;
                    i++;
                }
                else if (isDigit(s[i])) {
                    state = 1;
                    i++;
                }
                else if (s[i] == '.') {
                    state = 7;  // must be a digit
                    i++;
                }
                else if (s[i] == '+' || s[i] == '-') {
                    state = 9;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 1: // One digit is found
                if (isDigit(s[i])) {
                    state = 1;
                    i++;
                }
                else if (s[i] == '.') { // float 
                    state = 2;
                    i++;
                }
                else if (s[i] == 'e' || s[i] == 'E') { // scientific format
                    state = 3;
                    i++;
                }
                else if (s[i] == ' ') { // space
                    state = 4;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 2: // can be a digit or space
                if (isDigit(s[i])) {
                    state = 6; // float
                    i++;
                }
                else if (s[i] == ' ') {
                    state = 4;
                    i++;
                }
                else if (s[i] == 'e' || s[i] == 'E') {
                    state = 3;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 3: // scientific format
                if (s[i] == '+' || s[i] == '-') { // must be a digit
                    state = 8; // power value in scientific format
                    i++;
                }
                else if (isDigit(s[i])) {
                    state = 5;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 4:
                if (s[i] == ' ') {
                    state = 4;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 5: // power value of in scientific format
                if (isDigit(s[i])) {
                    state = 5;
                    i++;
                }
                else if (s[i] == ' ') {
                    state = 4;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 6: // float
                if (isDigit(s[i])) {
                    state = 6;
                    i++;
                }
                else if (s[i] == 'e' || s[i] == 'E') {
                    state = 3; // scientific format
                    i++;
                }
                //else if (s[i] == ' ' || s[i] == 'f') {
                else if (s[i] == ' ') {
                    state = 4;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 7: // must be a digit
                if (isDigit(s[i])) {
                    state = 6;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 8: // must a digit
                if (isDigit(s[i])) {
                    state = 5;
                    i++;
                }
                else {
                    return false;
                }
                break;
            case 9: // must be a digit
                if (isDigit(s[i])) {
                    state = 1;
                    i++;
                }
                else if (s[i] == '.') {
                    state = 7;
                    i++;
                }
                else {
                    return false;
                }
                break;
        }
    }
    
    if (state == 1 || state == 2 || state == 4 || state == 5 || state == 6) {
        return true;
    }
    else {
        return false;
    }
}

